#include "Encoding.h"
int32 UTF8Encoding::GetCharSize( uint32& charSize )
{
	charSize = 1;
	return R_SUCCEED;
}

int32 UTF8Encoding::GetByteSize( uint32& byteSize )
{
	byteSize = 6;
	return R_SUCCEED;
}

int32 UTF8Encoding::Decode( cbyte* bytes , uint32 byteSize , tchar* chars , uint32 charSize , uint32& useCharSize , uint32& useByteSize )
{
	if(byteSize == 0 || charSize == 0)
		return E_ENCODING_BUFFESIZE;

	cbyte* search = bytes + byteSize;

	while( search > bytes )
	{
		search--;
		if( *search < 0x80 )
		{
			search++;
			break;
		}
		if( *search >= 0xC0 )
		{
			break;
		}
	}

	uint32 offset = (uint32)( ( bytes + byteSize ) - search );
	
	if(      (*search & 0xFC ) == 0xFC )
		offset = offset != 6 ? offset : 0;
	else if( (*search & 0xF8 ) == 0xF8 )
		offset = offset != 5 ? offset : 0;
	else if( (*search & 0xF0 ) == 0xF0 )
		offset = offset != 4 ? offset : 0;
	else if( (*search & 0xE0 ) == 0xE0 )
		offset = offset != 3 ? offset : 0;
	else if( (*search & 0xC0 ) == 0xC0 )
		offset = offset != 2 ? offset : 0;

	byteSize = byteSize - offset;

	DWORD cvtSize = ::MultiByteToWideChar( CODE_PAGE_UTF8 , NULL , (LPCSTR)bytes , byteSize , (LPWSTR)chars , charSize );

	if( cvtSize == 0 )
	{
		useCharSize = byteSize;
		return E_ENCODING_MTOW;
	}
	else
	{
		useCharSize = cvtSize;
	}

	useByteSize = byteSize;

	return R_SUCCEED;
}

int32 UTF8Encoding::Encode( ctchar* chars , uint32 charSize , byte* bytes , uint32 byteSize , uint32& useCharSize , uint32& useByteSize )
{
	if( charSize == 0 || byteSize == 0 )
		return E_ENCODING_BUFFESIZE;

	DWORD cvtSize = ::WideCharToMultiByte( CODE_PAGE_UTF8 , NULL , chars , charSize , (LPSTR)bytes,byteSize,NULL,NULL);

	if( cvtSize == 0 )
	{
		uint32 uByteSize = 0;
		GetMaxByteSize( charSize , uByteSize );
		useByteSize = uByteSize;
		return E_ENCODING_WTOM;
	}
	else
	{
		useByteSize = cvtSize;
		useCharSize = charSize;
	}
	return R_SUCCEED;
}

int32 UTF8Encoding::GetCodePage( EncodingCodePage& codePage )
{
	codePage = CODE_PAGE_UTF8;
	return R_SUCCEED;
}

int32 UTF8Encoding::GetPerambleSize( uint32& perambleSize )
{
	if( m_preamble )
		perambleSize = 3;
	else
		perambleSize = 0;
	return R_SUCCEED;
}

int32 UTF8Encoding::GetPeramble( byte* bytes , cuint32& byteSize )
{
	if( ! m_preamble  )
		return R_SUCCEED;
	if( byteSize < 3 )
		return E_ENCODING_PREMABLE_SIZE;

	bytes[0] = 0xEF;
	bytes[1] = 0xBB;
	bytes[2] = 0xBF;

	return R_SUCCEED;
}

UTF8Encoding::UTF8Encoding(bool preamble ) : m_preamble( preamble )
{

}